// 
//  Copyright (C) 2009 Jacek Trubłajewicz
// 
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//  
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// 

using System;
using System.Drawing;
using System.Collections.Generic;
using HAKGERSoft;
using Mono.Unix;
using NLog;

namespace wxGadu
{
	
	
	public class StatusTrackingPanel : wx.Panel
	{
		private struct TrackingListItem
		{
			public int uin;
			public string name;
		}
		
		#region Id
		public enum Id
		{
			addButton = 1550,
			removeButton,
			showStatusChangeCheck,
			onlyAvailableCheck
		}
		#endregion
		
		#region sizers
		private wx.BoxSizer topSizer;
		private wx.BoxSizer boxSizer;
		private wx.BoxSizer contactsBoxSizer;
		private wx.BoxSizer availableBoxSizer;
		private wx.BoxSizer buttonsBoxSizer;
		private wx.BoxSizer trackedBoxSizer;
		private wx.StaticBoxSizer optionsStaticBoxSizer;
		private wx.StaticBoxSizer contactsStaticBoxSizer;
		private wx.FlexGridSizer optionsGrid;
		#endregion
		
		#region controls
		private wx.CheckBox showStatusChangeCheck;
		private wx.CheckBox onlyAvailableCheck;
		private wx.ListBox availableContacts;
		private wx.ListBox trackedContacts;
		private wx.StaticText availableST;
		private wx.StaticText trackedST;
		private wx.Button addButton;
		private wx.Button removeButton;
		private wx.StaticBox contactStaticBox;
		private wx.StaticBox optionsStaticBox;
		#endregion
		
		#region data members
		private ContactManager contactManager;
		private List<TrackingListItem> availableContactsList;
		private List<TrackingListItem> trackedContactsList;
		#endregion
		
#if LOG
		private Logger logger = LogManager.GetCurrentClassLogger();	
#endif
		
		public StatusTrackingPanel(wx.Window parent, int id, Point pos, Size size, uint style, ContactManager contactManager):
			base(parent, id, pos, size, style)
		{
			this.contactManager = contactManager;
			availableContactsList = new List<TrackingListItem>();
			trackedContactsList = new List<TrackingListItem>();
			
			DoControls();
			DoControlsProperties();
			DoLayout();
			
			EVT_BUTTON((int) Id.addButton, new wx.EventListener(OnAddButtonClicked));
			EVT_BUTTON((int) Id.removeButton, new wx.EventListener(OnRemoveButtonClicked));
		}
		
		private void DoControls()
		{
			addButton = new wx.Button(this, (int) Id.addButton, ">");
			removeButton = new wx.Button(this, (int) Id.removeButton, "<");
			showStatusChangeCheck = new wx.CheckBox(this, (int) Id.showStatusChangeCheck, 
			                                        Catalog.GetString("Show status changed notifications:"), 
			                                        wx.Window.wxDefaultPosition, wx.Window.wxDefaultSize,
			                                        wx.Alignment.wxALIGN_RIGHT);
			onlyAvailableCheck = new wx.CheckBox(this, (int) Id.onlyAvailableCheck, 
			                                        Catalog.GetString("Show only when became available/away:"), 
			                                        wx.Window.wxDefaultPosition, wx.Window.wxDefaultSize,
			                                        wx.Alignment.wxALIGN_RIGHT);
			availableContacts = new wx.ListBox(this, wx.Window.wxID_ANY);
			trackedContacts = new wx.ListBox(this, wx.Window.wxID_ANY);
			availableST = new wx.StaticText(this, Catalog.GetString("Available contacts:"));
			trackedST = new wx.StaticText(this, Catalog.GetString("Tracked contacts:"));
			contactStaticBox = new wx.StaticBox(this, Catalog.GetString("Contacts:"));
			optionsStaticBox = new wx.StaticBox(this, Catalog.GetString("Options:"));
		}
		
		private void DoControlsProperties()
		{
		}
		
		private void DoLayout()
		{
			topSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
			{
				boxSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
				{
					optionsStaticBoxSizer = new wx.StaticBoxSizer(optionsStaticBox, wx.Orientation.wxVERTICAL);
					{
						optionsGrid = new wx.FlexGridSizer(3, 2, 5, 5);
						{
							optionsGrid.Add(showStatusChangeCheck, 0, 0);
							optionsGrid.Add(20, 20, 0, 0, 0);
							optionsGrid.Add(onlyAvailableCheck, 0, 0);
							optionsGrid.Add(20, 20, 0, 0, 0);
							optionsGrid.Add(20, 40, 0, 0, 0);
						}
						optionsStaticBoxSizer.Add(optionsGrid, 1, wx.Stretch.wxEXPAND);
					}
					boxSizer.Add(optionsStaticBoxSizer, 0, wx.Stretch.wxEXPAND);
					
					
					contactsStaticBoxSizer = new wx.StaticBoxSizer(contactStaticBox, wx.Orientation.wxVERTICAL);
					{
						contactsBoxSizer = new wx.BoxSizer(wx.Orientation.wxHORIZONTAL);
						{
							availableBoxSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
							{
								availableBoxSizer.Add(availableST, 0, wx.Direction.wxBOTTOM|wx.Direction.wxTOP, 5);
								
								availableBoxSizer.Add(availableContacts, 1, wx.Stretch.wxEXPAND);
							}
							contactsBoxSizer.Add(availableBoxSizer, 1, wx.Stretch.wxEXPAND);
							
							
							buttonsBoxSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
							{
								buttonsBoxSizer.Add(20, 20, 1, 0, 0);
								buttonsBoxSizer.Add(addButton, 0, wx.Direction.wxALL, 5);
								buttonsBoxSizer.Add(removeButton, 0, wx.Direction.wxALL, 5);
								buttonsBoxSizer.Add(20, 20, 1, 0, 0);
							}
							contactsBoxSizer.Add(buttonsBoxSizer, 0, wx.Stretch.wxEXPAND);
							
							
							trackedBoxSizer = new wx.BoxSizer(wx.Orientation.wxVERTICAL);
							{
								trackedBoxSizer.Add(trackedST, 0, wx.Direction.wxBOTTOM|wx.Direction.wxTOP, 5);
								
								trackedBoxSizer.Add(trackedContacts, 1, wx.Stretch.wxEXPAND);
							}
							contactsBoxSizer.Add(trackedBoxSizer, 1, wx.Stretch.wxEXPAND);
							
						}
						contactsStaticBoxSizer.Add(contactsBoxSizer, 1, wx.Stretch.wxEXPAND);
					}
					boxSizer.Add(contactsStaticBoxSizer, 1, wx.Stretch.wxEXPAND);
				}
				topSizer.Add(boxSizer, 1, wx.Stretch.wxEXPAND|wx.Direction.wxALL, 5);
			}
			this.Sizer = topSizer;
			topSizer.SetSizeHints(this);
		}
		
		private void OnAddButtonClicked(object sender, wx.Event evt)
		{
			if (availableContacts.Selection == -1)
				return;
			
			int selection = availableContacts.Selection;
			
			if (selection > availableContactsList.Count - 1)
			{
#if LOG
				logger.Error(String.Format(Catalog.GetString(
	                             "Selected position on available contacts list box is: {0}, but available contact list has only {1} items. This should not happen!"),
				                           selection, availableContactsList.Count)
		                           );
#endif
				return;
			}
			// add contact to tracked list and list box
			trackedContactsList.Add(availableContactsList[selection]);
			trackedContacts.Append(String.Format("{0} [{1}]", 
			                                     availableContactsList[selection].name, 
			                                     availableContactsList[selection].uin));
			// remove it form available list and list box
			availableContactsList.RemoveAt(selection);
			availableContacts.Delete(selection);
				
		}
		
		private void OnRemoveButtonClicked(object sender, wx.Event evt)
		{
			if (trackedContacts.Selection == -1)
				return;
			
			int selection = trackedContacts.Selection;
			
			if (selection > trackedContactsList.Count - 1)
			{
#if LOG
				logger.Error(String.Format(Catalog.GetString(
	                             "Selected position on tracked contacts list box is: {0}, but tracked contact list has only {1} items. This should not happen!"),
						                           selection, trackedContactsList.Count)
		                           );
#endif
				return;
			}
			
			// add contact to available list and list box
			availableContactsList.Add(trackedContactsList[selection]);
			availableContacts.Append(String.Format("{0} [{1}]", 
			                                     trackedContactsList[selection].name, 
			                                     trackedContactsList[selection].uin));
			// remove it form tracked list and list box
			trackedContactsList.RemoveAt(selection);
			trackedContacts.Delete(selection);
		}
		
		
		public bool EnableStatusChangeNotify
		{
			get { return showStatusChangeCheck.Value; }
			set { showStatusChangeCheck.Value = value; }
		}
		
		
		public bool ShowOnlyAvailableNotify
		{
			get { return onlyAvailableCheck.Value; }
			set { onlyAvailableCheck.Value = value; }
		}			
		
		
		public List<int> TrackedList
		{
			set 
			{
				List<int> tracked = value;
				
				// clear contact lists
				trackedContactsList.Clear();
				availableContactsList.Clear();
				
				// for each contact in ContactsManager.Contacts list
				// check if is on tracked list and add into proper list
				foreach(ContactInfo ci in contactManager.Contacts.Values)
				{
					TrackingListItem contact = new TrackingListItem();
					contact.name = ci.Name;
					contact.uin = ci.Uin;
					if (tracked.Contains(ci.Uin))
					    trackedContactsList.Add(contact);
					else
						availableContactsList.Add(contact);
				}
				
				// clear list boxes
				availableContacts.Clear();
				trackedContacts.Clear();
				
				// insert contact into list boxes
				foreach (TrackingListItem avb in availableContactsList)
					availableContacts.Append(String.Format("{0} [{1}]", 
			                                     avb.name, 
			                                     avb.uin));
				
				foreach (TrackingListItem track in trackedContactsList)
					trackedContacts.Append(String.Format("{0} [{1}]", 
			                                     track.name, 
			                                     track.uin));			
			}
			
			get 
			{
				List<int> tracked = new List<int>();
				
				foreach (TrackingListItem track in trackedContactsList)
				{
					if (contactManager.Contacts.ContainsKey(track.uin))
						tracked.Add(track.uin);
				}
				
				return tracked;
			}
		}
		
	}
}
